package net.solvetheriddle.wwclient;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.solvetheriddle.wwclient.entity.Work;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpParams;

import android.util.Log;

/**
 * @author anoniim
 * 
 */
public class WWServer {

    // private static final String SERVER_URL =
    // "http://www.pensionunion.cz/workwatch/";
    private static final String SERVER_URL = "http://dev1.workwatch.cz/android/";
    private static final String RESPONSE = "* - result: ";
    private static final String LOGIN_URL = SERVER_URL + "login.php";
    private static final String ACTIVE_PROJECTS_URL = SERVER_URL + "aktualni_zakazky.php";
    private static final String ALL_PROJECTS_URL = SERVER_URL + "vsechny_zakazky.php";
    private static final String WORK_ON_PROJECT_URL = SERVER_URL + "prace_na_zakazce.php";
    private static final String WORK_URL = SERVER_URL + "prace.php";
    private static final String LOGOUT_URL = SERVER_URL + "logout.php";
    private static final String NEW_WORK_URL = SERVER_URL + "nova_prace.php";

    private static HttpClient httpClient = getThreadSafeClient();

    public WWServer() {
    }
    
    public static DefaultHttpClient getThreadSafeClient() {
	    DefaultHttpClient client = new DefaultHttpClient();
	    ClientConnectionManager mgr = client.getConnectionManager();
	    HttpParams params = client.getParams();
	 
	    client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, 
	            mgr.getSchemeRegistry()), params);
	 
	    return client;
    }

    public static InputStream loginUser(String company, String username, String password) throws IOException {
        HttpResponse httpResponse = sendLoginRequest(company, username, password);
        if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return httpResponse.getEntity().getContent();
        }
        return null;
    }

    public static boolean logoutUser() throws IOException {
        int statusCode = sendLogoutRequest().getStatusLine().getStatusCode();
        return statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT;
    }

    public static InputStream loadProjects() throws IOException {
        HttpResponse httpResponse;
        httpResponse = sendProjectsRequest(false);
        if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return httpResponse.getEntity().getContent();
        }
        return null;
    }

    public static InputStream loadWorkOnProject(long projectId) throws IOException {
        HttpResponse httpResponse = sendWorkOnProjectRequest(projectId);
        if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return httpResponse.getEntity().getContent();
        }
        return null;
    }

    /**
     * @param beginTime Time in millis when the work started.
     * @param endTime Time in millis when the work ended.
     * @return XML containing list of works. Null if the response is not 200 OK.
     * @throws IOException
     */
    public static InputStream loadWork(long beginTime, long endTime) throws IOException {
        HttpResponse httpResponse = sendWorkRequest(beginTime, endTime);
        if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return httpResponse.getEntity().getContent();
        }
        return null;
    }

    /**
     * @param notSentWork Work to be saved on server.
     * @return XML containing ID of saved work. Null if the response is not 200 OK.
     * @throws IOException
     */
    public static InputStream saveWork(Work notSentWork) throws IOException {
        HttpResponse httpResponse = sendNewWorkRequest(notSentWork.getProjectID(), notSentWork.getDescription(), notSentWork.getFrom(), notSentWork.getTo());
        if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            return httpResponse.getEntity().getContent();
        }
        return null;
    }

    /**
     * Handles the communication with server sending the POST request to all
     * work between <code>beginTime</code> and <code>endTime</code>.
     * 
     * @param beginTime
     *            time in millis
     * @param endTime
     *            time in millis
     * @return response from server containing XML file of work
     * @throws IOException
     */
    private static HttpResponse sendWorkRequest(long beginTime, long endTime) throws IOException {
        // establish connection
        HttpPost httpPost = new HttpPost(WORK_URL);
        // set parameters
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("od", WWParser.longToDate(beginTime)));
        nameValuePairs.add(new BasicNameValuePair("do", WWParser.longToDate(endTime)));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    /**
     * Handles the communication with server sending the POST request to login
     * the user.
     * 
     * @param company
     *            String set by user
     * @param username
     *            String set by user
     * @param password
     *            String set by user
     * @return response from server (containing XML file)
     * @throws IOException
     */
    private static HttpResponse sendLoginRequest(String company, String username, String password) throws IOException {
        // establish connection
        HttpPost httpPost = new HttpPost(LOGIN_URL);
        // set parameters
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("company", company));
        nameValuePairs.add(new BasicNameValuePair("username", username));
        nameValuePairs.add(new BasicNameValuePair("password", password));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    /**
     * Handles the communication with server sending the POST request to logout
     * the user.
     * 
     * @return response from server
     * @throws IOException
     */
    private static HttpResponse sendLogoutRequest() throws IOException {
        // establish connection
        HttpPost httpPost = new HttpPost(LOGOUT_URL);
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    /**
     * Handles the communication with server sending the POST request to insert
     * a new work.
     * 
     * @param projectId
     * @param description
     * @param beginTime
     * @param endTime
     * @return
     * @throws IOException
     */
    private static HttpResponse sendNewWorkRequest(long projectId, String description, long beginTime, long endTime) throws IOException {
        // establish connection
        HttpPost httpPost = new HttpPost(NEW_WORK_URL);
        // set parameters
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("id", String.valueOf(projectId)));
        nameValuePairs.add(new BasicNameValuePair("popis", description));
        nameValuePairs.add(new BasicNameValuePair("datum", WWParser.longToDate(beginTime)));
        nameValuePairs.add(new BasicNameValuePair("od", WWParser.longToTime(beginTime)));
        Log.d("WWCLIENT", WWParser.longToDate(beginTime));
        nameValuePairs.add(new BasicNameValuePair("do", WWParser.longToTime(endTime)));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    /**
     * Parses the given XML file for the list of projects.
     * 
     * @param onlyActive
     *            true if only active projects should be returned, false for all
     *            projects
     * @return response from server containing XML file of projects
     * @throws IOException
     */
    private static HttpResponse sendProjectsRequest(boolean onlyActive) throws IOException {
        // establish connection
        HttpPost httpPost;
        if (onlyActive) {
            httpPost = new HttpPost(ACTIVE_PROJECTS_URL);
        } else {
            httpPost = new HttpPost(ALL_PROJECTS_URL);
        }
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    /**
     * Handles the communication with server sending the POST request to get
     * work on certain project from server.
     * 
     * @param projectId
     *            Id of any project
     * @return List of work
     * @throws IOException
     */
    private static HttpResponse sendWorkOnProjectRequest(long projectId) throws IOException {
        // establish connection
        HttpPost httpPost = new HttpPost(WORK_ON_PROJECT_URL);
        // set parameters
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("id", String.valueOf(projectId)));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        // get response
        showPost(httpPost);
        HttpResponse response = httpClient.execute(httpPost);
        Log.d("WWCLIENT", RESPONSE + response.getStatusLine().toString());
        return response;
    }

    public static void showPost(HttpPost httpPost) {
        try {
            Log.d("WWCLIENT", "* Sending request: " + httpPost.getRequestLine().toString());
            HttpEntity hEntity = httpPost.getEntity();
            if (hEntity != null) {
                Log.d("WWCLIENT", "* - with parameters: " + WWParser.parseStringFromStream(hEntity.getContent()));
            }
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
